home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / x / gui / amiga / xfig.lha / src / x11 / e_rotate.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-26  |  11.5 KB  |  497 lines

  1. /*
  2.  * FIG : Facility for Interactive Generation of figures
  3.  * Copyright (c) 1985 by Supoj Sutanthavibul
  4.  *
  5.  * "Permission to use, copy, modify, distribute, and sell this software and its
  6.  * documentation for any purpose is hereby granted without fee, provided that
  7.  * the above copyright notice appear in all copies and that both the copyright
  8.  * notice and this permission notice appear in supporting documentation. 
  9.  * No representations are made about the suitability of this software for 
  10.  * any purpose.  It is provided "as is" without express or implied warranty."
  11.  */
  12.  
  13. #include "fig.h"
  14. #include "resources.h"
  15. #include "mode.h"
  16. #include "object.h"
  17. #include "paintop.h"
  18. #include "u_draw.h"
  19. #include "u_search.h"
  20. #include "u_create.h"
  21. #include "u_list.h"
  22. #include "w_canvas.h"
  23. #include "w_mousefun.h"
  24.  
  25. extern float    compute_angle();
  26.  
  27. static int    copy;
  28. static int    rotn_dirn;
  29. static int    init_rotate();
  30. static int    init_copynrotate();
  31. static int    rotate_selected();
  32. static int    rotate_search();
  33. static int    init_rotateline();
  34. static int    init_rotatetext();
  35.  
  36. rotate_cw_selected()
  37. {
  38.     rotn_dirn = 1;
  39.     rotate_selected();
  40. }
  41.  
  42. rotate_ccw_selected()
  43. {
  44.     rotn_dirn = -1;
  45.     rotate_selected();
  46. }
  47.  
  48. static
  49. rotate_selected()
  50. {
  51.     set_mousefun("rotate object", "copy & rotate", "");
  52.     canvas_kbd_proc = null_proc;
  53.     canvas_locmove_proc = null_proc;
  54.     init_searchproc_left(init_rotate);
  55.     init_searchproc_middle(init_copynrotate);
  56.     canvas_leftbut_proc = object_search_left;
  57.     canvas_middlebut_proc = object_search_middle;
  58.     canvas_rightbut_proc = null_proc;
  59.     set_cursor(pick15_cursor);
  60. }
  61.  
  62. static
  63. init_rotate(p, type, x, y, px, py)
  64.     char       *p;
  65.     int            type;
  66.     int            x, y;
  67.     int            px, py;
  68. {
  69.     copy = 0;
  70.     rotate_search(p, type, x, y, px, py);
  71. }
  72.  
  73. static
  74. init_copynrotate(p, type, x, y, px, py)
  75.     char       *p;
  76.     int            type;
  77.     int            x, y;
  78.     int            px, py;
  79. {
  80.     copy = 1;
  81.     rotate_search(p, type, x, y, px, py);
  82. }
  83.  
  84. static
  85. rotate_search(p, type, x, y, px, py)
  86.     char       *p;
  87.     int            type;
  88.     int            x, y;
  89.     int            px, py;
  90. {
  91.     switch (type) {
  92.     case O_POLYLINE:
  93.     cur_l = (F_line *) p;
  94.     init_rotateline(cur_l, px, py);
  95.     break;
  96.     case O_ARC:
  97.     cur_a = (F_arc *) p;
  98.     init_rotatearc(cur_a, px, py);
  99.     break;
  100.     case O_ELLIPSE:
  101.     cur_e = (F_ellipse *) p;
  102.     init_rotateellipse(cur_e, px, py);
  103.     break;
  104.     case O_SPLINE:
  105.     cur_s = (F_spline *) p;
  106.     init_rotatespline(cur_s, px, py);
  107.     break;
  108.     case O_TEXT:
  109.     cur_t = (F_text *) p;
  110.     init_rotatetext(cur_t, px, py);
  111.     break;
  112.     case O_COMPOUND:
  113.     cur_c = (F_compound *) p;
  114.     init_rotatecompound(cur_c, px, py);
  115.     break;
  116.     default:
  117.     return;
  118.     }
  119. }
  120.  
  121. static
  122. init_rotateline(l, px, py)
  123.     F_line       *l;
  124.     int            px, py;
  125. {
  126.     F_line       *line;
  127.  
  128.     set_temp_cursor(wait_cursor);
  129.     line = copy_line(l);
  130.     rotate_line(line, px, py, rotn_dirn);
  131.     if (copy) {
  132.     add_line(line);
  133.     } else {
  134.     toggle_linemarker(l);
  135.     draw_line(l, ERASE);
  136.     change_line(l, line);
  137.     }
  138.     draw_line(line, PAINT);
  139.     toggle_linemarker(line);
  140.     reset_cursor();
  141. }
  142.  
  143. static
  144. init_rotatetext(t, px, py)
  145.     F_text       *t;
  146.     int            px, py;
  147. {
  148.     F_text       *text;
  149.  
  150.     set_temp_cursor(wait_cursor);
  151.     text = copy_text(t);
  152.     rotate_text(text, px, py, rotn_dirn);
  153.     if (copy) {
  154.     add_text(text);
  155.     } else {
  156.     toggle_textmarker(t);
  157.     draw_text(t, ERASE);
  158.     change_text(t, text);
  159.     }
  160.     draw_text(text, PAINT);
  161.     toggle_textmarker(text);
  162.     reset_cursor();
  163. }
  164.  
  165. init_rotateellipse(e, px, py)
  166.     F_ellipse       *e;
  167.     int            px, py;
  168. {
  169.     F_ellipse       *ellipse;
  170.  
  171.     set_temp_cursor(wait_cursor);
  172.     ellipse = copy_ellipse(e);
  173.     rotate_ellipse(ellipse, px, py, rotn_dirn);
  174.     if (copy) {
  175.     add_ellipse(ellipse);
  176.     } else {
  177.     toggle_ellipsemarker(e);
  178.     draw_ellipse(e, ERASE);
  179.     change_ellipse(e, ellipse);
  180.     }
  181.     draw_ellipse(ellipse, PAINT);
  182.     toggle_ellipsemarker(ellipse);
  183.     reset_cursor();
  184. }
  185.  
  186. init_rotatearc(a, px, py)
  187.     F_arc       *a;
  188.     int            px, py;
  189. {
  190.     F_arc       *arc;
  191.  
  192.     set_temp_cursor(wait_cursor);
  193.     arc = copy_arc(a);
  194.     rotate_arc(arc, px, py, rotn_dirn);
  195.     if (copy) {
  196.     add_arc(arc);
  197.     } else {
  198.     toggle_arcmarker(a);
  199.     draw_arc(a, ERASE);
  200.     change_arc(a, arc);
  201.     }
  202.     draw_arc(arc, PAINT);
  203.     toggle_arcmarker(arc);
  204.     reset_cursor();
  205. }
  206.  
  207. init_rotatespline(s, px, py)
  208.     F_spline       *s;
  209.     int            px, py;
  210. {
  211.     F_spline       *spline;
  212.  
  213.     set_temp_cursor(wait_cursor);
  214.     spline = copy_spline(s);
  215.     rotate_spline(spline, px, py, rotn_dirn);
  216.     if (copy) {
  217.     add_spline(spline);
  218.     } else {
  219.     toggle_splinemarker(s);
  220.     draw_spline(s, ERASE);
  221.     change_spline(s, spline);
  222.     }
  223.     draw_spline(spline, PAINT);
  224.     toggle_splinemarker(spline);
  225.     reset_cursor();
  226. }
  227.  
  228. init_rotatecompound(c, px, py)
  229.     F_compound       *c;
  230.     int            px, py;
  231. {
  232.     F_compound       *compound;
  233.  
  234.     if (!valid_rot_angle(c)) {
  235.     put_msg("Invalid rotation angle for this compound object");
  236.     return;
  237.     }
  238.  
  239.     set_temp_cursor(wait_cursor);
  240.     compound = copy_compound(c);
  241.     rotate_compound(compound, px, py, rotn_dirn);
  242.     if (copy) {
  243.     add_compound(compound);
  244.     } else {
  245.     toggle_compoundmarker(c);
  246.     draw_compoundelements(c, ERASE);
  247.     change_compound(c, compound);
  248.     }
  249.     draw_compoundelements(compound, PAINT);
  250.     toggle_compoundmarker(compound);
  251.     reset_cursor();
  252. }
  253.  
  254. rotate_line(l, x, y, rotn_dirn)
  255.     F_line       *l;
  256.     int            x, y, rotn_dirn;
  257. {
  258.     F_point       *p;
  259.     int            dx;
  260.  
  261.     /* for speed we treat 90 degrees as a special case */
  262.     if (cur_rotnangle == 90) {
  263.     for (p = l->points; p != NULL; p = p->next) {
  264.         dx = p->x - x;
  265.         p->x = x + rotn_dirn * (y - p->y);
  266.         p->y = y + rotn_dirn * dx;
  267.     }
  268.     } else {
  269.     for (p = l->points; p != NULL; p = p->next)
  270.         rotate_point(p, x, y, rotn_dirn);
  271.     }
  272. }
  273.  
  274. rotate_spline(s, x, y, rotn_dirn)
  275.     F_spline       *s;
  276.     int            x, y, rotn_dirn;
  277. {
  278.     F_point       *p;
  279.     F_control       *cp;
  280.     int            dx;
  281.  
  282.     /* for speed we treat 90 degrees as a special case */
  283.     if (cur_rotnangle == 90) {
  284.     for (p = s->points; p != NULL; p = p->next) {
  285.         dx = p->x - x;
  286.         p->x = x + rotn_dirn * (y - p->y);
  287.         p->y = y + rotn_dirn * dx;
  288.     }
  289.     for (cp = s->controls; cp != NULL; cp = cp->next) {
  290.         dx = cp->lx - x;
  291.         cp->lx = x + rotn_dirn * (y - cp->ly);
  292.         cp->ly = y + rotn_dirn * dx;
  293.         dx = cp->rx - x;
  294.         cp->rx = x + rotn_dirn * (y - cp->ry);
  295.         cp->ry = y + rotn_dirn * dx;
  296.     }
  297.     } else {
  298.     for (p = s->points; p != NULL; p = p->next)
  299.         rotate_point(p, x, y, rotn_dirn);
  300.     if (int_spline(s))
  301.         remake_control_points(s);
  302.     }
  303. }
  304.  
  305. rotate_text(t, x, y, rotn_dirn)
  306.     F_text       *t;
  307.     int            x, y, rotn_dirn;
  308. {
  309.     int            dx;
  310.  
  311.     if (cur_rotnangle == 90) { /* treat 90 degs as special case for speed */
  312.     dx = t->base_x - x;
  313.     t->base_x = x + rotn_dirn * (y - t->base_y);
  314.     t->base_y = y + rotn_dirn * dx;
  315.     } else {
  316.     rotate_xy(&t->base_x, &t->base_y, x, y, rotn_dirn);
  317.     }
  318.     t->angle -= (float) (rotn_dirn * cur_rotnangle * M_PI / 180.0);
  319.     if (t->angle < 0.0)
  320.     t->angle += M_2PI;
  321.     else if (t->angle >= M_2PI - 0.001)
  322.     t->angle -= M_2PI;
  323.     reload_text_fstruct(t);
  324. }
  325.  
  326. rotate_ellipse(e, x, y, rotn_dirn)
  327.     F_ellipse       *e;
  328.     int            x, y, rotn_dirn;
  329. {
  330.     int            dxc,dxs,dxe;
  331.  
  332.     if (cur_rotnangle == 90) { /* treat 90 degs as special case for speed */
  333.     dxc = e->center.x - x;
  334.     dxs = e->start.x - x;
  335.     dxe = e->end.x - x;
  336.     e->center.x = x + rotn_dirn * (y - e->center.y);
  337.     e->center.y = y + rotn_dirn * dxc;
  338.     e->start.x = x + rotn_dirn * (y - e->start.y);
  339.     e->start.y = y + rotn_dirn * dxs;
  340.     e->end.x = x + rotn_dirn * (y - e->end.y);
  341.     e->end.y = y + rotn_dirn * dxe;
  342.     } else {
  343.     rotate_point(&e->center, x, y, rotn_dirn);
  344.     rotate_point(&e->start, x, y, rotn_dirn);
  345.     rotate_point(&e->end, x, y, rotn_dirn);
  346.     }
  347.     e->angle -= (float) (rotn_dirn * cur_rotnangle * M_PI / 180);
  348.     if (e->angle < 0.0)
  349.     e->angle += M_2PI;
  350.     else if (e->angle >= M_2PI - 0.001)
  351.     e->angle -= M_2PI;
  352. }
  353.  
  354. rotate_arc(a, x, y, rotn_dirn)
  355.     F_arc       *a;
  356.     int            x, y, rotn_dirn;
  357. {
  358.     int            dx;
  359.     F_pos        p[3];
  360.     float        xx, yy;
  361.  
  362.     /* for speed we treat 90 degrees as a special case */
  363.     if (cur_rotnangle == 90) {
  364.     dx = a->center.x - x;
  365.     a->center.x = x + rotn_dirn * (y - a->center.y);
  366.     a->center.y = y + rotn_dirn * dx;
  367.     dx = a->point[0].x - x;
  368.     a->point[0].x = x + rotn_dirn * (y - a->point[0].y);
  369.     a->point[0].y = y + rotn_dirn * dx;
  370.     dx = a->point[1].x - x;
  371.     a->point[1].x = x + rotn_dirn * (y - a->point[1].y);
  372.     a->point[1].y = y + rotn_dirn * dx;
  373.     dx = a->point[2].x - x;
  374.     a->point[2].x = x + rotn_dirn * (y - a->point[2].y);
  375.     a->point[2].y = y + rotn_dirn * dx;
  376.     } else {
  377.     p[0] = a->point[0];
  378.     p[1] = a->point[1];
  379.     p[2] = a->point[2];
  380.     rotate_point(&p[0], x, y, rotn_dirn);
  381.     rotate_point(&p[1], x, y, rotn_dirn);
  382.     rotate_point(&p[2], x, y, rotn_dirn);
  383.     if (compute_arccenter(p[0], p[1], p[2], &xx, &yy)) {
  384.         a->point[0].x = p[0].x;
  385.         a->point[0].y = p[0].y;
  386.         a->point[1].x = p[1].x;
  387.         a->point[1].y = p[1].y;
  388.         a->point[2].x = p[2].x;
  389.         a->point[2].y = p[2].y;
  390.         a->center.x = xx;
  391.         a->center.y = yy;
  392.         a->direction = compute_direction(p[0], p[1], p[2]);
  393.     }
  394.     }
  395. }
  396.  
  397. /* checks to see if the objects within c can be rotated by cur_rotnangle */
  398.  
  399. valid_rot_angle(c)
  400.     F_compound     *c;
  401. {
  402.     F_line         *l;
  403.     F_compound     *c1;
  404.  
  405.     if (cur_rotnangle == 90)
  406.     return 1; /* always valid */
  407.     for (l = c->lines; l != NULL; l = l->next)
  408.     if (l->type == T_ARC_BOX || l->type == T_BOX)
  409.         return 0;
  410.     for (c1 = c->compounds; c1 != NULL; c1 = c1->next)
  411.     if (!valid_rot_angle(c1))
  412.         return 0;
  413.     return 1;
  414. }
  415.  
  416. rotate_compound(c, x, y, rotn_dirn)
  417.     F_compound       *c;
  418.     int            x, y, rotn_dirn;
  419. {
  420.     F_line       *l;
  421.     F_arc       *a;
  422.     F_ellipse       *e;
  423.     F_spline       *s;
  424.     F_text       *t;
  425.     F_compound       *c1;
  426.  
  427.     for (l = c->lines; l != NULL; l = l->next)
  428.     rotate_line(l, x, y, rotn_dirn);
  429.     for (a = c->arcs; a != NULL; a = a->next)
  430.     rotate_arc(a, x, y, rotn_dirn);
  431.     for (e = c->ellipses; e != NULL; e = e->next)
  432.     rotate_ellipse(e, x, y, rotn_dirn);
  433.     for (s = c->splines; s != NULL; s = s->next)
  434.     rotate_spline(s, x, y, rotn_dirn);
  435.     for (t = c->texts; t != NULL; t = t->next)
  436.     rotate_text(t, x, y, rotn_dirn);
  437.     for (c1 = c->compounds; c1 != NULL; c1 = c1->next)
  438.     rotate_compound(c1, x, y, rotn_dirn);
  439.  
  440.     /*
  441.      * Make the bounding box exactly match the dimensions of the compound.
  442.      */
  443.     compound_bound(c, &c->nwcorner.x, &c->nwcorner.y,
  444.            &c->secorner.x, &c->secorner.y);
  445. }
  446.  
  447. rotate_point(p, x, y, rotn)
  448.     F_point       *p;
  449.     int            x, y, rotn;
  450. {
  451.     /* rotate point p about coordinate (x, y) */
  452.     int            dx, dy;
  453.     float        cosa, sina, mag, theta;
  454.  
  455.     dx = p->x - x;
  456.     dy = y - p->y;
  457.     if (dx == 0 && dy == 0)
  458.     return;
  459.  
  460.     theta = compute_angle((float) dx, (float) dy);
  461.     theta -= (float) (rotn_dirn * cur_rotnangle * M_PI / 180.0);
  462.     if (theta < 0.0)
  463.     theta += M_2PI;
  464.     else if (theta >= M_2PI - 0.001)
  465.     theta -= M_2PI;
  466.     mag = sqrt((double) (dx * dx + dy * dy));
  467.     cosa = mag * cos((double) theta);
  468.     sina = mag * sin((double) theta);
  469.     p->x = x + cosa;
  470.     p->y = y - sina;
  471. }
  472.  
  473. rotate_xy(orig_x, orig_y, x, y, rotn)
  474.     int             *orig_x, *orig_y, x, y, rotn;
  475. {
  476.     /* rotate coord (orig_x, orig_y) about coordinate (x, y) */
  477.     int             dx, dy;
  478.     float           cosa, sina, mag, theta;
  479.  
  480.     dx = *orig_x - x;
  481.     dy = y - *orig_y;
  482.     if (dx == 0 && dy == 0)
  483.     return;
  484.  
  485.     theta = compute_angle((float) dx, (float) dy);
  486.     theta -= (float) (rotn_dirn * cur_rotnangle * M_PI / 180.0);
  487.     if (theta < 0.0)
  488.     theta += M_2PI;
  489.     else if (theta >= M_2PI - 0.001)
  490.     theta -= M_2PI;
  491.     mag = sqrt((double) (dx * dx + dy * dy));
  492.     cosa = mag * cos((double) theta);
  493.     sina = mag * sin((double) theta);
  494.     *orig_x = x + cosa;
  495.     *orig_y = y - sina;
  496. }
  497.